package com.sansan.qiangji.controller.warehouse;

import com.sansan.qiangji.VO.warehouse.stackerTaskIn.StackerTaskInVO;
import com.sansan.qiangji.VO.warehouse.stackerTaskMove.StackerTaskMoveVO;
import com.sansan.qiangji.config.RedisConfig;
import com.sansan.qiangji.enums.RedisLockKeyEnum;
import com.sansan.qiangji.enums.ResultEnum;
import com.sansan.qiangji.exception.ServiceException;

import com.sansan.qiangji.form.warehouse.*;
import com.sansan.qiangji.realize.warehouse.PushOrderDetailReal;
import com.sansan.qiangji.resultVO.ResultVO;
import com.sansan.qiangji.task.AsyncTask;
import com.sansan.qiangji.utils.RedisLockUtil;
import com.sansan.qiangji.utils.ResultVOUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import redis.clients.jedis.Jedis;

import javax.validation.Valid;
import java.util.Objects;
import java.util.UUID;

@CrossOrigin()
@RequestMapping("/pushOrderDetail")
@RestController
@Slf4j
public class PushOrderDetailController {
    @Autowired
    private PushOrderDetailReal pushOrderDetailReal;
    @Autowired
    private RedisConfig redisConfig;
    @Autowired
    private AsyncTask asyncTask;

    @PostMapping("/addPushOrderDetail")
    public ResultVO<Object> addPushOrderDetail(@Valid @RequestBody PushOrderDetailAddForm pushOrderDetailAddForm, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            log.error("【入库单详情新增】参数不正确，pushOrderDetailAddForm={}", pushOrderDetailAddForm);
            throw new ServiceException(ResultEnum.PARAM_ERROR.getCode(), Objects.requireNonNull(bindingResult.getFieldError()).getDefaultMessage());
        }
        pushOrderDetailReal.addPushOrderDetail(pushOrderDetailAddForm);
        return ResultVOUtil.success(null);
    }

    @PostMapping("/getPushOrderDetailList")
    public ResultVO<Object> getPushOrderDetailList(@Valid @RequestBody PushOrderDetailListForm form, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            log.error("【入库单详情查询】参数不正确，pushOrderDetailAddForm={}", form);
            throw new ServiceException(ResultEnum.PARAM_ERROR.getCode(), Objects.requireNonNull(bindingResult.getFieldError()).getDefaultMessage());
        }
        return ResultVOUtil.success(pushOrderDetailReal.pushOrderDetailList(form));
    }

    @PostMapping("/editPushOrderDetail")
    public ResultVO<Object> editPushOrderDetail(@Valid @RequestBody PushOrderDetailEditForm pushOrderDetailEditForm, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            log.error("【入库单详情修改】参数不正确，pushOrderDetailAddForm={}", pushOrderDetailEditForm);
            throw new ServiceException(ResultEnum.PARAM_ERROR.getCode(), Objects.requireNonNull(bindingResult.getFieldError()).getDefaultMessage());
        }
        pushOrderDetailReal.editPushOrderDetail(pushOrderDetailEditForm);
        return ResultVOUtil.success(null);
    }

    @PostMapping("/deletePushOrderDetail")
    public ResultVO<Object> deletePushOrderDetail(@RequestParam(value = "pushOrderDetailId") Integer pushOrderDetailId) {
        pushOrderDetailReal.deletePushOrderDetail(pushOrderDetailId);
        return ResultVOUtil.success(null);
    }

    @PostMapping("productBindingBox")
    public ResultVO<Object> productBindingBox(@Valid @RequestBody ProductBindingBoxForm productBindingBoxForm, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            log.error("【入库单详情修改】参数不正确，productBindingBoxForm={}", productBindingBoxForm.toString());
            throw new ServiceException(ResultEnum.PARAM_ERROR.getCode(), Objects.requireNonNull(bindingResult.getFieldError()).getDefaultMessage());
        }
        pushOrderDetailReal.productBindingBox(productBindingBoxForm);
        return ResultVOUtil.success(null);
    }

    @PostMapping("/productBindingStock")
    public ResultVO<Object> productBindingStock(@Valid @RequestBody ProductBindingStockForm form, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            log.error("【创建入库任务】参数不正确，ProductBindingStockForm={}", form.toString());
            throw new ServiceException(ResultEnum.PARAM_ERROR.getCode(), Objects.requireNonNull(bindingResult.getFieldError()).getDefaultMessage());
        }
        Jedis jedis = new Jedis(redisConfig.getHost(), redisConfig.getPort());
        String requestId = UUID.randomUUID().toString();
        if (!redisConfig.getPassword().equals("")) {
            jedis.auth(redisConfig.getPassword());
        }
        try {
            StackerTaskInVO stackerTaskInVO = new StackerTaskInVO();
            for (int i = 0; i < 5; i++) {
                if (!RedisLockUtil.tryGetDistributedLock(jedis, RedisLockKeyEnum.STACKER_TASK_LOCK.getKey(), requestId, 5000)) {
                    if (i == 4) {
                        log.error("【任务执行】系统任务繁忙 !");
                        throw new ServiceException(ResultEnum.STACKER_TASK_BUSY);
                    }
                    try {
                        Thread.sleep(1000);
                    } catch (Exception ignored) {
                    }
                    continue;
                }
                stackerTaskInVO = pushOrderDetailReal.productBindingStock(form);
                asyncTask.pushProduct(stackerTaskInVO.getStackerTaskInCode());
                break;
            }
            jedis.close();
            RedisLockUtil.releaseDistributedLock(jedis, RedisLockKeyEnum.STACKER_TASK_LOCK.getKey(), requestId);
            return ResultVOUtil.success(stackerTaskInVO);
        } catch (Exception e) {
            jedis.close();
            RedisLockUtil.releaseDistributedLock(jedis, RedisLockKeyEnum.STACKER_TASK_LOCK.getKey(), requestId);
            throw e;
        }
    }

    @PostMapping("/stackerTaskInContinue")
    public ResultVO<Object> stackerTaskInContinue(@RequestParam(value = "stackerTaskInCode") String stackerTaskInCode,
                                                  @RequestParam(value = "stackerTaskInPace") String stackerTaskInPace) {
        Jedis jedis = new Jedis(redisConfig.getHost(), redisConfig.getPort());
        String requestId = UUID.randomUUID().toString();
        if (!redisConfig.getPassword().equals("")) {
            jedis.auth(redisConfig.getPassword());
        }
        try {
            for (int i = 0; i < 5; i++) {
                if (!RedisLockUtil.tryGetDistributedLock(jedis, RedisLockKeyEnum.STACKER_TASK_LOCK.getKey(), requestId, 5000)) {
                    if (i == 4) {
                        log.error("【任务执行】系统任务繁忙 !");
                        throw new ServiceException(ResultEnum.STACKER_TASK_BUSY);
                    }
                    try {
                        Thread.sleep(1000);
                    } catch (Exception ignored) {
                    }
                    continue;
                }
                pushOrderDetailReal.stackerTaskInContinue(stackerTaskInCode, stackerTaskInPace);
                asyncTask.pushProduct(stackerTaskInCode);
                break;
            }
            jedis.close();
            RedisLockUtil.releaseDistributedLock(jedis, RedisLockKeyEnum.STACKER_TASK_LOCK.getKey(), requestId);
            return ResultVOUtil.success(null);
        } catch (Exception e) {
            jedis.close();
            RedisLockUtil.releaseDistributedLock(jedis, RedisLockKeyEnum.STACKER_TASK_LOCK.getKey(), requestId);
            throw e;
        }
    }

    @PostMapping("/moveStockPosition")
    public ResultVO<Object> moveStockPosition(@Valid @RequestBody MoveStockForm form) {
        Jedis jedis = new Jedis(redisConfig.getHost(), redisConfig.getPort());
        String requestId = UUID.randomUUID().toString();
        if (!redisConfig.getPassword().equals("")) {
            jedis.auth(redisConfig.getPassword());
        }
        try {
            StackerTaskMoveVO stackerTaskMoveVO = new StackerTaskMoveVO();
            for (int i = 0; i < 5; i++) {
                if (!RedisLockUtil.tryGetDistributedLock(jedis, RedisLockKeyEnum.STACKER_TASK_LOCK.getKey(), requestId, 5000)) {
                    if (i == 4) {
                        log.error("【任务执行】系统任务繁忙 !");
                        throw new ServiceException(ResultEnum.STACKER_TASK_BUSY);
                    }
                    try {
                        Thread.sleep(1000);
                    } catch (Exception ignored) {
                    }
                    continue;
                }
                stackerTaskMoveVO = pushOrderDetailReal.moveStockPosition(form);
                asyncTask.moveProduct(stackerTaskMoveVO.getStackerTaskMoveCode());
                break;
            }
            jedis.close();
            RedisLockUtil.releaseDistributedLock(jedis, RedisLockKeyEnum.STACKER_TASK_LOCK.getKey(), requestId);
            return ResultVOUtil.success(stackerTaskMoveVO);
        } catch (Exception e) {
            jedis.close();
            RedisLockUtil.releaseDistributedLock(jedis, RedisLockKeyEnum.STACKER_TASK_LOCK.getKey(), requestId);
            throw e;
        }
    }

    @PostMapping("/stackerTaskMoveContinue")
    public ResultVO<Object> stackerTaskMoveContinue(@RequestParam(value = "stackerTaskMoveCode") String stackerTaskMoveCode,
                                                  @RequestParam(value = "stackerTaskMovePace") String stackerTaskMovePace){
        Jedis jedis = new Jedis(redisConfig.getHost(), redisConfig.getPort());
        String requestId = UUID.randomUUID().toString();
        if (!redisConfig.getPassword().equals("")) {
            jedis.auth(redisConfig.getPassword());
        }
        try {
            for (int i = 0; i < 5; i++) {
                if (!RedisLockUtil.tryGetDistributedLock(jedis, RedisLockKeyEnum.STACKER_TASK_LOCK.getKey(), requestId, 5000)) {
                    if (i == 4) {
                        log.error("【任务执行】系统任务繁忙 !");
                        throw new ServiceException(ResultEnum.STACKER_TASK_BUSY);
                    }
                    try {
                        Thread.sleep(1000);
                    } catch (Exception ignored) {
                    }
                    continue;
                }
                pushOrderDetailReal.stackerTaskMoveContinue(stackerTaskMoveCode, stackerTaskMovePace);
                asyncTask.moveProduct(stackerTaskMoveCode);
                break;
            }
            jedis.close();
            RedisLockUtil.releaseDistributedLock(jedis, RedisLockKeyEnum.STACKER_TASK_LOCK.getKey(), requestId);
            return ResultVOUtil.success(null);
        } catch (Exception e) {
            jedis.close();
            RedisLockUtil.releaseDistributedLock(jedis, RedisLockKeyEnum.STACKER_TASK_LOCK.getKey(), requestId);
            throw e;
        }
    }
}
